package com.zhangfb95.crosschain.plugin.container.java.fabric2.service.chaincodeevent;

import com.zhangfb95.crosschain.infra.exception.BusinessException;
import com.zhangfb95.crosschain.infra.model.Result;
import com.zhangfb95.crosschain.infra.util.UuidUtil;
import com.zhangfb95.crosschain.infra.util.json.JsonUtil;
import com.zhangfb95.crosschain.plugin.container.java.fabric2.infra.data.api.crosschainserver.PluginApi;
import com.zhangfb95.crosschain.plugin.container.java.fabric2.infra.model.enums.ChaincodeEventEnum;
import com.zhangfb95.crosschain.plugin.container.java.fabric2.infra.model.mapper.entity.Fabric2TxEvent;
import com.zhangfb95.crosschain.plugin.container.java.fabric2.infra.model.service.dto.CrossSendEventPayload;
import com.zhangfb95.crosschain.protocol.exc.request.SendExcReq;
import com.zhangfb95.crosschain.protocol.exc.response.SendExcRes;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author zhangfubing
 * @since 2024/1/9
 */
@Slf4j
@Service
public class CrossSendChaincodeEventHandler extends AbstractChaincodeEventHandler<Void> {

    @Autowired
    private JsonUtil jsonUtil;
    @Autowired
    private PluginApi pluginApi;

    @Override
    public ChaincodeEventEnum event() {
        return ChaincodeEventEnum.CROSS_SEND_EVENT;
    }

    @Override
    protected Result<Void> handle(Fabric2TxEvent fabric2TxEvent, Result<Void> preAfterResult) {
        // 生成处理序列
        String seq = UuidUtil.uuid();

        // 反序列化事件负载
        log.info("cross send start, seq: {}, payload: {}", seq, fabric2TxEvent.getEventPayload());
        CrossSendEventPayload crossSendEventPayload;
        try {
            crossSendEventPayload = jsonUtil.readValue(fabric2TxEvent.getEventPayload(), CrossSendEventPayload.class);
        } catch (BusinessException e) {
            CrossSendEventPayload sample = new CrossSendEventPayload()
                    .setUserId(1L)
                    .setServerId("${serverId}")
                    .setChainPath("${chainPath}")
                    .setMethod("${method}")
                    .setArgs(new String[]{"${param1}", "${param2}"});
            String sampleJson = jsonUtil.toJsonQuietly(sample);
            log.info("cross send read payload fail, seq: {}, should like: {}", seq, sampleJson);
            return Result.fail(e.getCode(), e.getMessage());
        }
        log.info("cross send read payload success, seq: {}", seq);

        // 跨链发送交易
        log.info("cross send before, seq: {}", seq);
        try {
            Result<SendExcRes> excResult = pluginApi.send(new SendExcReq()
                    .setServerId(crossSendEventPayload.getServerId())
                    .setUserId(crossSendEventPayload.getUserId())
                    .setChainPath(crossSendEventPayload.getChainPath())
                    .setMethod(crossSendEventPayload.getMethod())
                    .setArgs(crossSendEventPayload.getArgs()));
            Result<Void> result = excResult.copy();
            if (!result.isSuccess()) {
                log.info("cross send fail, seq: {}, code: {}, msg: {}", seq, result.getCode(), result.getMsg());
                return result;
            }
            log.info("cross send success, seq: {}", seq);
        } catch (RuntimeException e) {
            log.info("cross send exception, seq: {}, msg: {}", seq, e.getMessage(), e);
            return Result.fail(e.getMessage());
        }

        return Result.ok();
    }
}
